package com.neuedu.utils;


import freemarker.template.TemplateException;
import org.apache.commons.text.WordUtils;

import java.awt.*;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 项目：mblog_java4
 * 创建时间：  2021-12-28   10:46
 * 作者 :jshand
 * 描述 : 生成Dao
 * 使用jdbc 查询出数据库 有那些表,
 * 循环表集合
 * 1 生成dao
 * 使用UserDao当做模板，替换类名、替换表明、替换字段名
 * 使用Freemarker作为模板引擎
 */
public class Generator {

    private static Connection connection = null;
    private static final  String tablePrefix = "mto_"; //表明前缀
    private static final  String ignoreTables = "mto_user";
    //所有表名字
    private static List<String> tablesNameList = new ArrayList<>();
    //所有表信息
    private static List<Table> tablesList = new ArrayList<>();


    //包路径相关
    public static final String destDir = "D:\\generator\\";
    public static final String entityPackage = "com.neuedu.mblog.entity";
    public static final String daoPackage = "com.neuedu.mblog.dao";



    //程序入口
    public static void main(String[] args) throws Exception {
        //初始化
        init();
        //1 查询由多少张表
        getTables();

        //2 解析每张表的字段结构
        analysisAllTableColumn();

        //3 生成实体类(lombok形式)
        generatorEntitys();

        //4 生成Dao类
        generatorDaos();


        //关闭资源
        close();
    }

    private static void generatorDaos() throws IOException, TemplateException {
        for (Table table : tablesList) {
            String ftlName = "dao.ftl";
            Object data = table;
            //实体类的路径
            String destFileDir = destDir+"/src/main/java/"+daoPackage.replace(".","/");
            String destFile = destFileDir +"/"+table.getDaoName()+".java";

            //生成文件
            FtlUtils.generator(ftlName,data,destFile);
        }
    }

    private static void generatorEntitys() throws IOException, TemplateException {

        for (Table table : tablesList) {
            String ftlName = "entity.ftl";
            Object data = table;
            //实体类的路径
            String destFileDir = destDir+"/src/main/java/"+entityPackage.replace(".","/");
            String destFile = destFileDir +"/"+table.getEntityName()+".java";

            //生成文件
            FtlUtils.generator(ftlName,data,destFile);
        }


    }


    //2 解析每张表的字段结构
    private static void analysisAllTableColumn() throws Exception {
        if(tablesNameList == null ||tablesNameList.size() ==0){
            System.out.println("未查询到数据库的表名");
            return;
        }
        for (String tableName : tablesNameList) {
            analysisSingleTableColumn(tableName);
        }

    }

    //分析单张表的数据结构
    private static void  analysisSingleTableColumn(String name) throws Exception {
        if(connection == null){
            throw new Exception("连接数据库异常");
        }

        System.out.println("准备解析表【"+name+"】的字段信息");

        //解析后结果应该存放在table对象中
        Table table = new Table();
        table.setTableName(name);
        //表明去掉前缀后首字母变大写
        table.setEntityName(WordUtils.capitalize(name.replace(tablePrefix, "")));
        table.setDaoName(table.getEntityName()+"Dao");


        //解析表字段主键列
        DatabaseMetaData dmd = connection.getMetaData();
        ResultSet dmdRs = dmd.getPrimaryKeys(null, "%", name);
        if(dmdRs.next()){
            table.setPkColumnName(dmdRs.getString("column_name"));
        }



        String sql = "select * from  "+name;
        Statement stmt = connection.createStatement();

        ResultSet rs = stmt.executeQuery(sql);
        //获取查询结果的元数据 用于分析表结构
        ResultSetMetaData meta = rs.getMetaData();
        //返回一共有多少列
        int columnCount = meta.getColumnCount();
        table.setColumnCount(columnCount);
        //解析每一列的信息
        //JDBC从1 开始序号
        for (int i = 1; i <=columnCount; i++) {
            //列名字
            String columnLabel = meta.getColumnLabel(i);
            //数据类型，对应java.sql.Types里面的常量
            int columnType = meta.getColumnType(i);
            //数据类型的名字，如varchar、varchar2等，这个只是作为参考，程序判断时使用的是columnType
            String columnTypeName = meta.getColumnTypeName(i);

            Column column = new Column(columnLabel,columnType,columnTypeName);
            table.addcolumnList(column);
            //追加列名字
            //1 全部字段
            table.appendColumnNames(columnLabel);
            //2 排除主键列.
            if(table.getPkColumnName()== null || !table.getPkColumnName().equalsIgnoreCase(columnLabel)){
                table.appendUnPkcolumnNames(columnLabel);
            }else{
                //主键列的信息
                table.setPkColumn(column);
            }
        }


        //收集所有表信息
        tablesList.add(table);

    }



    //1 查询由多少张表
    private static void getTables() throws Exception {

        if(connection == null){
            throw new Exception("连接数据库异常");
        }


        //获取数据库元数据
        DatabaseMetaData meta = connection.getMetaData();
        ResultSet tableResult = meta.getTables(connection.getCatalog(), "root", null, new String[]{"TABLE"});
        while (tableResult.next()){
            String tableName  = tableResult.getString("TABLE_NAME");
            System.out.println("查询到数据库中存在的表  tableName = " + tableName);
            //如果是忽略的表，则不处理
            if(ignoreTables.contains(tableName)){
                continue;
            }
            tablesNameList.add(tableName);
        }

        if(tableResult != null){
            tableResult.close();
        }
    }



    //获取数据库连接
    private static void init() throws ClassNotFoundException, SQLException {


        String username = "root";
        String password = "root";
        String url = "jdbc:mysql://127.0.0.1:3306/mto_blog";
        String driverClass = "com.mysql.jdbc.Driver";

        Class.forName("com.mysql.jdbc.Driver");
        connection =  DriverManager.getConnection(url,username,password);
    }

    private static void close() throws SQLException {
        if(connection != null){
            connection.close();
        }
    }





}
